
#include <assert.h>
#include <stdlib.h>
#include "utility.h"
#include "qr-common.h"
#include "frame-filler.h"

FrameFiller* frame_filler_new(unsigned char* frame, int version)
{
	int width;
	FrameFiller* frame_filler;

	if(NULL == frame || qr_check_version(version) < 0)
	{
		RES_NULL("Argument is invalid.");
	}

	width = qr_width(version);
	if(width <= 0)
	{
		RES_NULL("Invoke qr_width error.");
	}
	frame_filler = (FrameFiller*)malloc(sizeof(FrameFiller));
	if(NULL == frame_filler)
	{
		RES_NULL("Invoke malloc error.");
	}
	frame_filler->_frame = frame;
	frame_filler->_width = width;
	frame_filler->_x = width - 1;
	frame_filler->_y = width - 1;
	frame_filler->_state = FILL_STATE_INVALID;
	frame_filler->_direction = FILL_DIRECTION_UPPER;
	return frame_filler;
}

void frame_filler_destroy(FrameFiller* frame_filler)
{
	if(frame_filler != NULL)
	{
		free(frame_filler);
	}
}

unsigned char* frame_filler_next(FrameFiller* frame_filler)
{
	unsigned char* frame, * result;
	int width, x, y;

	if(NULL == frame_filler)
	{
		RES_NULL("Argument is invalid.");
	}

	frame = frame_filler->_frame;
	width = frame_filler->_width;
	x = frame_filler->_x;
	y = frame_filler->_y;
	if(FILL_STATE_INVALID == frame_filler->_state)
	{
		frame_filler->_state = FILL_STATE_LEFT_BLANK;
//		frame_filler->_x = width - 1;
//		frame_filler->_y = width - 1;
		assert(width - 1 == x && width - 1 == y);
		return frame + y * width + x;
	}
	switch(frame_filler->_state)
	{
		case FILL_STATE_LEFT_BLANK:
			{
				--x;
				frame_filler->_state = FILL_STATE_LEFT_FULL;
			}
			break;
		case FILL_STATE_LEFT_FULL:
			{
				++x;
				y += frame_filler->_direction;
				frame_filler->_state = FILL_STATE_LEFT_BLANK;
			}
			break;
		case FILL_STATE_INVALID:
		default:
			{
				assert(FALSE);
			}
			break;
	}
	switch(frame_filler->_direction)
	{
		case FILL_DIRECTION_UPPER:
			{
				if(y < 0)
				{
					y = 0;
					x -= 2;
					frame_filler->_direction = FILL_DIRECTION_LOWER;
					if(6 == x)
					{
						--x;
						y = 9;
					}
				}
			}
			break;
		case FILL_DIRECTION_LOWER:
			{
				if(width == y)
				{
					y = width - 1;
					x -= 2;
					frame_filler->_direction = FILL_DIRECTION_UPPER;
					if(6 == x)
					{
						--x;
						y -= 8;
					}
				}
			}
			break;
		default:
			{
				assert(FALSE);
			}
			break;
	}
	if(x >= 0 && y >= 0)
	{
		assert(x < width && y < width);
		frame_filler->_x = x;
		frame_filler->_y = y;
		if(0 == (frame[y * width + x] & 0x80))
		{
			result = frame + y * width + x;
		}
		else
		{
			result = frame_filler_next(frame_filler);
		}
	}
	else
	{
		result = NULL;
	}
	return result;
}

